package com.lx.base.exception;


import lombok.Getter;
import org.slf4j.MDC;
import org.springframework.util.StringUtils;

import java.util.concurrent.ExecutionException;


public class BaseException extends RuntimeException {

    @Getter
    private final CodeMessage codeMessage;

    @Getter
    private String extMsg;

    @Getter
    private boolean defaulted;

    @Getter
    private boolean sendEmail = false;


    protected BaseException(CodeMessage codeMessage) {
        this(codeMessage, null, null);
    }

    protected BaseException(CodeMessage codeMessage, String extMsg) {
        this(codeMessage, null, extMsg);
    }


    protected BaseException(CodeMessage codeMessage, Throwable t) {
        this(codeMessage, t, null);
    }


    protected BaseException(CodeMessage codeMessage, Throwable t, String extMsg) {
        super(getMessage(codeMessage, extMsg), t);
        if (codeMessage == null) {
            codeMessage = CommonError.SYSTEM_ERROR;
        }
        this.extMsg = extMsg;
        this.codeMessage = codeMessage;
        this.defaulted = false;
    }

    protected BaseException(boolean sendEmail, CodeMessage codeMessage, Throwable t, String extMsg) {
        super(getMessage(codeMessage, extMsg), t);
        if (codeMessage == null) {
            codeMessage = CommonError.SYSTEM_ERROR;
        }
        this.extMsg = extMsg;
        this.codeMessage = codeMessage;
        this.defaulted = false;
        this.sendEmail = sendEmail;
    }

    protected BaseException(CodeMessage codeMessage, Throwable t, String extMsg, boolean defaulted) {
        super(getMessage(codeMessage, extMsg), t);
        if (codeMessage == null) {
            codeMessage = CommonError.SYSTEM_ERROR;
        }
        this.extMsg = extMsg;
        this.codeMessage = codeMessage;
        this.defaulted = defaulted;
    }


    public static BaseException orNew(Throwable t, CodeMessage codeMessage) {
        return orNew(t, codeMessage, null);
    }


    public static BaseException orNew(Throwable t, CodeMessage codeMessage, String extMsg) {
        // 如果是线程池抛出的ExecutionException，则获取其cause
        if (t instanceof ExecutionException) {
            t = t.getCause();
        }

        if (t instanceof BaseException) {
            return (BaseException) t;
        } else {
            // 根据状态码是否为系统错误，创建SysException或BizException
            if (codeMessage == null || CommonError.SYSTEM_ERROR.getCode().equals(codeMessage.getCode())) {
                return new SysException(t, extMsg);
            } else {
                return new BizException(codeMessage, t, extMsg);
            }
        }
    }

    private static String getMessage(CodeMessage codeMessage, String extMsg) {
        StringBuilder sb = new StringBuilder();
        codeMessage = codeMessage != null ? codeMessage : CommonError.SYSTEM_ERROR;
        sb.append(codeMessage.getCode()).append("::").append(codeMessage.getMsg());
        if (!StringUtils.isEmpty(extMsg)) {
            sb.append("::").append(extMsg);
        }
        try {
            String traceId = MDC.get("X-B3-TraceId");
            if (!StringUtils.isEmpty(traceId)) {
                sb.append("::").append(traceId);
            }
        } catch (Throwable e) {
        }

        return sb.toString();
    }
}
